﻿using JESAI.EventBus.EventBusStores;
using JESAI.EventBus.Events;
using JESAI.EventBus.ExcutedResults;
using JESAI.EventBus.Helpers;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JESAI.EventBus.PublishManagers
{
    public class EventPublishManager : IEventPublishManager
    {
        public event EventHandler<EventHandleResult> OnGrobalPublishedCallBack;

        private readonly IEventStore _eventStore;
        public void GrobalPublishedCallback(EventHandleResult result)
        {
            try
            {
                OnGrobalPublishedCallBack?.Invoke(this, result);
            }
            catch { }
        }

        public EventPublishManager(IEventStore eventStore)
        {
            _eventStore = eventStore;
        }

        public async Task PublishAsync(IEvent eventSource)
        {
            await _eventStore.Push(eventSource, eventSource.CancellationToken);
        }

        public async Task PublishAsync(string eventId, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(eventId, payload, cancellationToken));
        }

        public async Task PublishAsync(Enum eventId, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(eventId, payload, cancellationToken));
        }

        public async Task PublishAsync<T>(T eventId, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(Helper.ParseToString<T>(eventId), payload, cancellationToken));
        }

        public Task PublishDelayAsync(IEvent eventSource, long delay)
        {
            // 创建新线程
            Task.Factory.StartNew(async () =>
            {
                // 延迟 delay 毫秒
                await Task.Delay(TimeSpan.FromMilliseconds(delay), eventSource.CancellationToken);

                await _eventStore.Push(eventSource, eventSource.CancellationToken);
            }, eventSource.CancellationToken);

            return Task.CompletedTask;
        }

        public async Task PublishDelayAsync(string eventId, long delay, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishDelayAsync(new PublishEvent(eventId, payload, cancellationToken), delay);
        }

        public async Task PublishDelayAsync(Enum eventId, long delay, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishDelayAsync(new PublishEvent(eventId, payload, cancellationToken), delay);
        }

        public async Task PublishDelayAsync<T>(T eventId, long delay, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishDelayAsync(new PublishEvent(Helper.ParseToString<T>(eventId), payload, cancellationToken), delay);
        }


        public async Task PublishTimerAsync(string eventId, DateTime dateTime, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(eventId, payload, dateTime, cancellationToken));
        }

        public async Task PublishTimerAsync(Enum eventId, DateTime dateTime, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(eventId, payload, dateTime, cancellationToken));
        }

        public async Task PublishTimerAsync<T>(T eventId, DateTime dateTime, object payload = null, CancellationToken cancellationToken = default)
        {
            await PublishAsync(new PublishEvent(Helper.ParseToString<T>(eventId), payload, dateTime, cancellationToken));
        }
    }
}
